package com.yhh;

import com.yhh.Entity.Command;
import com.yhh.Entity.HandlerCommand;
import com.yhh.Exceptions.InstructionException;
import com.yhh.Exceptions.NonInstructionException;
import com.yhh.myUtils.CommandUtils;

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.Map;

import static com.yhh.ClientThread.uncheckFilename;
import static com.yhh.ClientThread.uncheckKey;

class RecvCommand extends Command implements HandlerCommand {
    private static final String c = "recv";
    private DataInputStream dis;
    private FileOutputStream fos;
    private final String directory = ClientThread.directory;

    protected RecvCommand(Socket socket) {
        super(socket);
        command.add("-m");
        command.add("-r");
    }

    @Override
    public void handlerParameter(Map<String, String> args) throws InstructionException, NonInstructionException {
        if (args.get("-m") == null || args.get("-m").length() != 10) {
            throw new InstructionException("-m参数有误", c);
        }
    }

    @Override
    public boolean check(Map<String, String> args) throws NonInstructionException, InstructionException {
        //处理指令参数
        handlerParameter(args);
        checkParameter(args);
        return true;
    }

    @Override
    public void handlerCommand(Map<String, String> args) throws InstructionException, NonInstructionException {
        if(args.get("-r")!=null){
            //重传
            try {
                handlerResend();
            }catch (FileNotFoundException e){
                System.out.println("文件不存在");
                return;
            }
        }
        String resp = recvMsg();
        if (resp.equals("ready")) {
            handlerRecv(args);
            sendMsg("success");
        } else {
            System.out.println(resp);
        }

    }

    //处理接受文件函数
    public void handlerRecv(Map<String, String> args) {
        File recvCache = new File(System.getProperty("user.dir") + File.separatorChar + "recvCacheFile");
        FileOutputStream fosCache = null;
        try {
            dis = new DataInputStream(socket.getInputStream());
            // 文件名和长度
            String fileName = dis.readUTF();
            long fileLength = dis.readLong();
            File Directory = new File(directory);
            if (!Directory.exists()) {
                Directory.mkdir();
            }

            File file = new File(directory + File.separatorChar + fileName);

            fosCache = new FileOutputStream(recvCache);

            //记录当前正在传输的key
            fosCache.write((fileName + "\n").getBytes(StandardCharsets.UTF_8));
            fosCache.write((args.get("-m") + "\n").getBytes(StandardCharsets.UTF_8));
            fosCache.flush();


            fos = new FileOutputStream(file);
            // 开始接收文件
            byte[] bytes = new byte[1024];
            long l = fileLength / 1024 / 100;
            long _fileLength = fileLength;
            long progress = 0;
            int length = 0;
            long i = l;
            System.out.println("开始接收文件,文件大小为:" + CommandUtils.getFormatFileSize(fileLength));
            while ((length = dis.read(bytes, 0, bytes.length)) != -1) {
                progress += length;
                fileLength -= length;
                fos.write(bytes, 0, length);
                fos.flush();
                if (i-- == 0) {
                    System.out.print("| " + (100 * progress / _fileLength) + "% |");
                    i = l;
                }
                if (fileLength <= 0) break;
            }
            fosCache.close();
            recvCache.delete();
            //接受成功标志

            System.out.println();
            System.out.println("======== 文件接收成功 [File Name：" + fileName + "] ========");
            System.out.println("======== 文件路径 [" + file.getAbsolutePath() + "] ========");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (fos != null)
                    fos.close();
                if (fosCache != null)
                    fosCache.close();
            } catch (Exception e) {
            }
        }
    }

    //处理重传函数
    private void handlerResend() throws FileNotFoundException {
        if (uncheckFilename == null || uncheckKey == null) {
            throw new FileNotFoundException();
        }
        String resp = recvMsg();
        if(!"ready".equals(resp)){
            System.out.println(resp);
            return;
        }
        //获取文件名和长度
        File file = new File(directory + File.separatorChar + uncheckFilename);
        if (!file.exists()) {
            throw new FileNotFoundException();
        }
        String fileName = file.getName();
        //本地文件长度
        long _length = file.length();
        //指定追加文件
        FileOutputStream fileFos = new FileOutputStream(file, true);

        try {
            //发送未完成文件的key
            sendMsg(uncheckKey);
            //发送本地文件的key
            sendMsg(String.valueOf(_length));

            String resp2 = recvMsg();

            if ("ready".equals(resp2)) {
                dis = new DataInputStream(socket.getInputStream());
                long fileLength = dis.readLong();
                long _fileLength = fileLength;
                System.out.println("准备传输");
                byte[] bytes = new byte[1024];
                long l = fileLength / 1024 / 100;
                long i = l;
                long progress = _length;
                //还要减去当前所存
                fileLength -= _length;
                System.out.println("开始接收文件,文件大小为:" + CommandUtils.getFormatFileSize(_fileLength));
                int length = 0;
                while ((length = dis.read(bytes, 0, bytes.length)) != -1) {
                    progress += length;
                    fileLength -= length;
                    fileFos.write(bytes, 0, length);
                    fileFos.flush();
                    if (i-- == 0) {
                        System.out.print("| " + (100 * progress / _fileLength) + "% |");
                        i = l;
                    }
                    if (fileLength <= 0) break;
                }

                File recvCache = new File(System.getProperty("user.dir") + File.separatorChar + "recvCacheFile");
                System.out.println(recvCache);
                if (recvCache.exists()) recvCache.delete();
                sendMsg("success");
                System.out.println();
                System.out.println("======== 文件接收成功 [File Name：" + fileName + "] ========");
                System.out.println("======== 文件路径 [" + file.getAbsolutePath() + "] ========");
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
